/***********************************
 *           3/24/2014             *
 *       by Meow dev (arm genesis) *
 *                                 *
 ***********************************/
package com.meow.dev.engine;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import com.meow.dev.constante.EnrollmentConstance;
import com.meow.dev.constante.EnrollmentConstance.PassWordType;
import com.meow.dev.constante.EnrollmentConstance.UserType;
import com.meow.dev.constante.ErrorCode;
import com.sun.jna.NativeLong;
import com.sun.jna.ptr.LongByReference;
import com.sun.jna.ptr.NativeLongByReference;


public class PB7Engine implements IFPEngine{
	
	private final static Logger LOGGER = Logger.getLogger(PB7Engine.class.getName());
	private FKAttendDLLMapping attendDLLMapping;
	private NativeLong connectionResult;
	private static long PORT = 5005;
	private static long MACHINE_NO = 1;
	private static long TIMEOUT = 1;
	private static long TCP = 0;
	private static long NET_PASSWORD = 0;
	private static long LICENSE = 1263;
	private static String IP_ADDR = "192.168.1.222";
	
	public PB7Engine() {
		LOGGER.info("### Engine start ####");
		attendDLLMapping = FKAttendDLLMapping.INSTANCE;
		connectionResult = ErrorCode.RUNERR_NO_OPEN_COMM;

	}
	
	@Override
	public long connect(String ipAddr,long port,long machineNo){
		IP_ADDR = ipAddr;
		PORT = port;
		MACHINE_NO = machineNo;
		return connect().longValue();
	}
	
	public NativeLong connect() {
		LOGGER.info("##### START CONNECT ######");
		connectionResult = attendDLLMapping.FK_ConnectNet(new NativeLong(MACHINE_NO),
				IP_ADDR, new NativeLong(PORT), new NativeLong(TIMEOUT),
				new NativeLong(TCP), new NativeLong(NET_PASSWORD), new NativeLong(LICENSE));
		LOGGER.info("### RESULT  :  " + connectionResult + " >> " + ErrorCode.ERRORTYPE.MSG.getMsg(connectionResult.intValue()));
		return connectionResult;
	}
	
	@Override
	public List<UserData> getALLEnroll_UserData(){
//		************** set pointer *********************
		List<UserData> listData = new ArrayList<UserData>();
		
		LOGGER.info("##### GET USER DATA #####");
		boolean SECCESS = true;
		NativeLong re = attendDLLMapping.FK_ReadAllUserID(connectionResult);
		LOGGER.info("+set pointer to read USER DATA : " + re);
		if(!re.equals(ErrorCode.RUN_SUCCESS)){
			LOGGER.info("##### ERROR ID : #####" + re);
			SECCESS = false;
		}
		
//		**************** load data *********************
		LongByReference apnEnrollNumber = new LongByReference();
		LongByReference apnBackupNumber = new LongByReference();
		LongByReference apnMachinePrivilege = new LongByReference();
		LongByReference apnEnableFlag = new LongByReference();
		NativeLong loadUser = ErrorCode.RUNERR_NO_OPEN_COMM;
		// load when true
		if(SECCESS)
		while(true){
			loadUser = attendDLLMapping.FK_GetAllUserID(connectionResult,apnEnrollNumber,apnBackupNumber,apnMachinePrivilege,apnEnableFlag);
			if(loadUser.equals(ErrorCode.RUNERR_DATAARRAY_END))	break;
			if(loadUser.equals(ErrorCode.RUN_SUCCESS)){
				UserData data  = new UserData();
				data.setEnrollNumber(apnEnrollNumber.getValue());
				data.setBackupNumber(apnBackupNumber.getValue());
				data.setMachinePrivilege(apnMachinePrivilege.getValue());
				data.setEnableFlag( apnEnableFlag.getValue() );
				listData.add(data);
//				LOGGER.info("ADD : " + listData.size());
			}
		}
		LOGGER.info("Load usersize : " + listData.size());
		
		return listData;
	}
	
	@Override
	public UserDataEncode getEnrollEncode(long EnrollNumber, long BackupNumber) {
		LOGGER.info(" start EnrollNumber : " + EnrollNumber  + " BK : " + BackupNumber);
		NativeLongByReference pnMachinePrivilege = new NativeLongByReference();
		NativeLongByReference passWordAndCard = new NativeLongByReference();
		long[] fingerData = new long[459];
		
		NativeLong res = attendDLLMapping.FK_GetEnrollData(connectionResult,
				new NativeLong(EnrollNumber), new NativeLong(BackupNumber),
				pnMachinePrivilege, fingerData, passWordAndCard);
		LOGGER.info("Load result : " + res);
		
//		System.out.println("NUMBER " + EnrollNumber + "  RES : " + res);
//		System.out.println("FK_GetEnrollData : " + passWordAndCard.getValue());
//		System.out.println("FK_GetEnrollData : " + fingerData[0]);
		if(res.equals(ErrorCode.RUN_SUCCESS)){
			UserDataEncode userDataEncode = new UserDataEncode();
			userDataEncode.setFingerData(fingerData);
			userDataEncode.setPasswordAndCard(passWordAndCard.getValue().longValue());
			return userDataEncode;
		}else{
			LOGGER.info("error id: " + EnrollNumber);
		}
		
		return null;
	}
	
	@Override
	public void addUser(long userId, UserType type, PassWordType passWordType, UserDataEncode dataEncode) {
		LOGGER.info(" Start ");
		attendDLLMapping.FK_EnableDevice(connectionResult, EnrollmentConstance.DEVICE_WORKING);
		
		NativeLong nEnrollNumber = new NativeLong(userId);
		NativeLong nBackupNumber = passWordType.getType();
		NativeLong nMachinePrivilege = type.getType();
		long[] pnEnrollData = dataEncode.getFingerData();
		NativeLong nPassWord = new NativeLong(dataEncode.getPasswordAndCard());
		
		NativeLong res =attendDLLMapping.FK_PutEnrollData(connectionResult, nEnrollNumber,
				nBackupNumber, nMachinePrivilege, pnEnrollData, nPassWord);
		
		if(res.equals(ErrorCode.RUN_SUCCESS)){
			res = attendDLLMapping.FK_SaveEnrollData(connectionResult);
			LOGGER.info("success Userid : " + userId + "Type : " + passWordType.getType());
		}else{
			LOGGER.info("error : " + res);
		}
		
		attendDLLMapping.FK_EnableDevice(connectionResult, EnrollmentConstance.DEVICE_FINISH);

	}
	
	@Override
	public List<UserData>  getAllUserID(){
		attendDLLMapping.FK_EnableDevice(connectionResult, EnrollmentConstance.DEVICE_WORKING);
		List<UserData> userlist = this.getALLEnroll_UserData();
		LOGGER.info(" Start : workin size : " + userlist.size());
		for( UserData u : userlist ){
			 UserDataEncode encode = this.getEnrollEncode(u.getEnrollNumber(), u.getBackupNumber());
			 u.setDataEncode(encode);
//			 System.out.println(u);
		}
		LOGGER.info(" finish " );
		
		attendDLLMapping.FK_EnableDevice(connectionResult, EnrollmentConstance.DEVICE_FINISH);
		
		return userlist;
	}
	
	@Override
	public boolean resetDevice(){
		LOGGER.info("#### reset : ");

		boolean finish = false;
		attendDLLMapping.FK_EnableDevice(connectionResult, EnrollmentConstance.DEVICE_WORKING);
		NativeLong res = attendDLLMapping.FK_ClearKeeperData(connectionResult);
		if(!res.equals(ErrorCode.RUN_SUCCESS)){
			LOGGER.info("#### Error : " + res);
		}
		attendDLLMapping.FK_EnableDevice(connectionResult, EnrollmentConstance.DEVICE_FINISH);
		return finish;

	}
	
	@Override
	public boolean removeUser(long userId, PassWordType type){
		LOGGER.info( "remove  id : " + userId + " type " + type);
		boolean finish = true;
		attendDLLMapping.FK_EnableDevice(connectionResult, EnrollmentConstance.DEVICE_WORKING);
		
		NativeLong res = attendDLLMapping.FK_DeleteEnrollData(connectionResult, new NativeLong(userId), type.getType());
		
		if(!res.equals(ErrorCode.RUN_SUCCESS)){
			LOGGER.info( "## Error id : " + userId + " type " + type + " Error Code : " + res);
			finish = false;
		}
		attendDLLMapping.FK_EnableDevice(connectionResult, EnrollmentConstance.DEVICE_FINISH);
		return finish;
	}
	
	@Override
	public List<UserLog> getLogUser() {
		LOGGER.info(" start " );
		attendDLLMapping.FK_EnableDevice(connectionResult,EnrollmentConstance.DEVICE_WORKING);
		List<UserLog> list = new ArrayList<UserLog>();
		
		LongByReference apnEnrollNumber = new LongByReference();
		LongByReference pnVerifyMode = new LongByReference();
		LongByReference apnInOutMode = new LongByReference();
		LongByReference apnYear = new LongByReference();
		LongByReference apnMonth = new LongByReference();
		LongByReference apnDay = new LongByReference();
		LongByReference apnHour = new LongByReference();
		LongByReference apnMinute = new LongByReference();
		LongByReference apnSec = new LongByReference();
		
		attendDLLMapping.FK_LoadGeneralLogData(connectionResult, EnrollmentConstance.ReadMark_READ_ALL);
		NativeLong res = ErrorCode.RUNERR_NON_CARRYOUT;
		
		boolean running = true;
			do {
			res= attendDLLMapping.FK_GetGeneralLogData_1(connectionResult,
					apnEnrollNumber, pnVerifyMode, apnInOutMode, apnYear, apnMonth,
					apnDay, apnHour, apnMinute, apnSec);
//			System.out.println(res);
			if (res.equals(ErrorCode.RUN_SUCCESS)) {
				UserLog userLog = new UserLog();
				userLog.setUserId(apnEnrollNumber.getValue());
				userLog.setVerifyMode(pnVerifyMode.getValue());
				userLog.setInOutMode(apnInOutMode.getValue());
				userLog.setYear(apnYear.getValue());
				userLog.setMonth(apnMonth.getValue());
				userLog.setDay(apnDay.getValue());
				userLog.setHour(apnHour.getValue());
				userLog.setMin(apnMinute.getValue());
				userLog.setSec(apnSec.getValue());
				list.add(userLog);
			}else{
				LOGGER.info("### " + res);
				running = false;
			}
			
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				running = false;
			}
		}while(running);
		
		
		System.out.println("######## log size " + list.size());
		
		attendDLLMapping.FK_EnableDevice(connectionResult,EnrollmentConstance.DEVICE_FINISH);
		
		return list;

	}
	
	@Override
	public boolean clearUserLog() {
		attendDLLMapping.FK_EnableDevice(connectionResult,EnrollmentConstance.DEVICE_WORKING);
		NativeLong res = attendDLLMapping.FK_EmptyGeneralLogData(connectionResult);
		boolean finnish = true;
		if (!res.equals(ErrorCode.RUN_SUCCESS)) {
			LOGGER.info("##Error : " + res);
			finnish = false;
		}

		attendDLLMapping.FK_EnableDevice(connectionResult,EnrollmentConstance.DEVICE_FINISH);
		return finnish;
	}
	
	@Override
	public long serverStaus() {
		return this.getConnectionResult().longValue();
	}
	
	@Override
	public long reConnect() {
		return this.connect().longValue();
	}
	
	public FKAttendDLLMapping getAttendDLLMapping() {
		return attendDLLMapping;
	}

	public NativeLong getConnectionResult() {
		return connectionResult;
	}

	public static void main(String[] args) {
//		PB7Engine pb7Engine = new PB7Engine();
//		
//		pb7Engine.connect();
		
//		pb7Engine.getEnrollOne(99L,UserData.BACKUP_PSW);
//		pb7Engine.getEnrollOne(5L,UserData.BACKUP_PSW);
//		pb7Engine.getEnrollOne(6L,UserData.BACKUP_PSW);
//		pb7Engine.getEnrollOne(3L,UserData.BACKUP_CARD);
//		long[] fingerdata = pb7Engine.getEnrollOne(113L,UserData.BACKUP_FINGER_P);
//		pb7Engine.addUser(113,fingerdata);
		
		
		
//		pb7Engine.resetDevice();
		
//		UserDataEncode dataEncode = new UserDataEncode();
//		dataEncode.setPasswordAndCard(1234);
//		pb7Engine.addUser(2, UserType.USER, PassWordType.CARD, dataEncode);
//		pb7Engine.addUser(55, UserType.USER, PassWordType.PASSWORD, dataEncode);
//		pb7Engine.removeUser(1,PassWordType.CARD);
//		List<UserData> list = pb7Engine.getAllUserID();
//		for(UserData u : list){
//			System.out.println(u);
//		}
//		LogToFile logToFile = new LogToFile();
//		logToFile.writeLog(list);
//		List<UserData> l = logToFile.readLog(LogToFile.LOG_FILE_NAME);
//		System.out.println(l.size());
		
//		List<UserLog> list = pb7Engine.getLogUser();
//		logToFile.writeUserLog(list);
//		
//		for(UserLog l  : list){
//			System.out.println(l);
//			System.out.println(l.toString_1());
//		}
//		pb7Engine.clearUserLog();
//		RealTimeData realTimeData = new RealTimeData( pb7Engine.getAttendDLLMapping(), pb7Engine.getConnectionResult());
//		Thread t = new Thread(realTimeData);
//		t.start();
		
	}


}
